/*
 *  DocumentMemory.java
 *
 *  Chau, Sau Ming
 *
 *  August 14, 2000
 *
 *  This file defines the DocumentMemory class. DocumentMemory and together with
 *  StopMemory (defined in StopMemory.java) are a Java wrapper to the C
 *  implementation (WinNT) of the Extractor algorithms developed at NRC by
 *  Peter Turney. For more information about Extractor, visit
 *  http://extractor.iit.nrc.ca. This implementation uses Extractor 6.0.
 *  This is an extention of Extractor.java (first Java wrapper to Extractor)
 *  developed at NRC by Marvin Zaluski.
 *
 *  What is added
 *    - allow multiple documents processed in a single- or multi-thread
 *      environment.
 *
 *  Dependencies: For example, SignalDocumentEnd() should only be called
 *  after ReadDocumentBuffer has been called. For efficiency reasons,
 *  Extractor does not verify that the functions are called in the
 *  correct order. The programmer is responsible for ensuring that the
 *  dependencies are observed in the program that invokes Extractor.
 *  Please refer to http://extractor.iit.nrc.ca for details.
 *
 *  - Important -  Class path containing the Extractor Wrapper dll or so
 *  must be specified in order to function properly.  For example, in WinNT,
 *  go to Control Panel -> System -> Environment and type the path
 *  (e.g. C:\App) in Class path text box.  For more information
 *  about setting class path, please refer to Java website java.sun.com.
 */


public class DocumentMemory
{
  //  Character Code ISO-8859-1
  public final static int CharCodeISO_8859_1 = 0;
  
  //  Character Code MS-DOS
  public final static int CharCodeMS_DOS = 1;
  
  //  Character Code Unicode-UCS2
  public final static int CharCodeUnicode_UCS2 = 2;
  
  //  Character Code Shft-JIS
  public final static int CharCodeShft_JIS = 3;
  
  //  Character Code JIS
  public final static int CharCodeJIS = 4;
  
  //  Character Code EUC-jp
  public final static int CharCodeEUC_jp = 5;

  //  Language ID for Automatic Language Detection
  public final static int LanguageAUTOMATIC = 0;
  
  //  Language ID for English Language Detection
  public final static int LanguageENGLISH = 1;
  
  //  Language ID for French Language Detection
  public final static int LanguageFRENCH = 2;
  
  //  Language ID for Japanese Language Detection
  public final static int LanguageJAPANESE = 3;
  
  //  Language ID for German Language Detection
  public final static int LanguageGERMAN = 4;

  //  Default Highlight Type
  public final static int Highlight00000000 = 0;
  
  //  Highlight Type - Remove Duplicate Sentences Highlight Type
  public final static int Highlight00000001 = 1;
  
  //  Highlight Type - Order Of Appearance In Text Highlight Type
  public final static int Highlight00000010 = 2;
  
  //  Highlight Type - Use Full Sentence Highlight Type
  public final static int Highlight00000100 = 4;
  
  //  Highlight Type - Markup Important Words Highlight Type
  public final static int Highlight00001000 = 8;
  
  //  Highlight Type - Markup Unimportant Words Highlight Type
  public final static int Highlight00010000 = 16;

  //  Property ID - get the number of words that were read 
  public final static int PropID_Number_Word_Read = 1;
  
  //  Property ID - get the number of non-stop words (content words) that were read 
  public final static int PropID_Number_NonStop_Word_Read = 2;

  //  Property ID - see whether the whole document was read 
  //                (0 = only the beginning of the document was read;
  //                 1 = the whole document was read) 
  public final static int PropID_Whole_Document_Read = 3;


  private long lng_document_mem_ptr;  // Pointer to stop memory
  private boolean bln_valid;          // Indicate validity of DocumentMemory object
  private int int_last_return_code;   // Return code of last operation
  private int int_output_code;        // Output character code 
  private StopMemory StopMem;         // StopMemory object
  
  
  /*
   *  DocumentMemory
   &
   *  Constructor
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - none
   *
   *  public DocumentMemory()
   */
  public DocumentMemory(StopMemory Stop_Memory)
  {
    lng_document_mem_ptr = -1;  // Invalid pointer value
    bln_valid = false;          // Not properly constructed
    StopMem = Stop_Memory;      // Reference to StopMemeory passed
    int_output_code = 0;        // Set default output character code
    CreateDocumentMemory();     // Create a stop memory through Extractor
  }

  
  /*
   *  isValid
   *
   *  Return true if DocumentMemory object is properly constructor; otherwise,
   *` return false.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (boolean) validity of this DocumentMemory object
   *
   *  isValid()
   */
  public boolean isValid()
  {
    return bln_valid;
  }

  
  /*
   *  GetReturnCode
   *
   *  Return the return code of last operation.  For more information, please
   *  refer to http://extractor.iit.nrc.ca/api.html.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) return code of last operation
   *  
   *  public int GetReturnCode()
   */
  public int GetReturnCode()
  {
    return int_last_return_code;
  }

  
  /*
   *  GetStopMemory
   *
   *  Return the StopMemory associate with this DocumentMemory.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (StopMemory) StopMemory object
   *  
   *  public StopMemory GetStopMemory()
   */
  public StopMemory GetStopMemory()
  {
    return StopMem;
  }

  
  /*
   *  GetDocumentMemoryPointer
   *
   *  Return the document memory pointer.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (long) document memory pointer
   *
   *  public long GetDocumentMemoryPointer()
   */
  public long GetDocumentMemoryPointer()
  {
    return lng_document_mem_ptr;
  }


  /*
   *  CreateDocumentMemory
   *
   *  Create a document memory only if it is not properly constructed (i.e.
   *  document memory not yet created by Extractor through native method
   *  CreateDocumentMemory_helper()).
   *
   *  Arguments
   *    - none.
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  public int CreateDocumentMemory()
   */
  public int CreateDocumentMemory()
  {
    if (!bln_valid)
    { // Create document memory through CreateStopMemory_helper().
      if ((int_last_return_code = CreateDocumentMemory_helper()) == 0)
      { // Document memory created successfully.
        bln_valid = true;
      }
    }
    else
    {
      int_last_return_code = 0;
    }
    return int_last_return_code;
  }

  /*
   *  ClearDocumentMemory
   *
   *  Clear the document memory and free up space used by document memory.
   *  It is done only if the DocumentMemory is properly constructed.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  public int ClearDocumentMemory()
   */
  public int ClearDocumentMemory()
  {
    if (bln_valid)
    { // Stop memory is constructed.
      int_last_return_code = ClearDocumentMemory_helper(lng_document_mem_ptr);
      if (int_last_return_code == 0)
      {
        lng_document_mem_ptr = -1;
        bln_valid = false;
      }
      else
      {
        int_last_return_code = 0;
      }
    }
    return int_last_return_code;
  }

  
  /*
   *  GetErrorMessage
   *
   *  Return error message correspond to the input error code number.
   *
   *  Arguments
   *    1. (int) error code
   *
   *  Return
   *    - (String) error message
   *
   *  GetErrorMessage(int errorCode)
   */
  public String GetErrorMessage(int errorCode)
  {
    if (errorCode == 0)
    {
      return new String("ERROR: All is OK. No errors were detected.");
    }
    else if (errorCode > 0)
    {
      return GetErrorMessage_helper(errorCode);

    }
    else
    {
      return new String("ERROR: Error Code is UNKNOWN.");
    }
  }

  
  /*
   *  ActivateHighlights
   *
   *  Activate highlight extraction.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  ActivateHighlights()
   */
  public int ActivateHighlights()
  {
    return ActivateHighlights_helper(lng_document_mem_ptr);
  }

  
  /*
   *  ActivateHTMLFilter
   *
   *  This function signals that the document DocumentMemory contains HTML
   *  tags. By default, it is assumed that the document does not contain
   *  HTML tags.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  ActivateHTMLFilter()
   */
  public int ActivateHTMLFilter()
  {
    return ActivateHTMLFilter_helper(lng_document_mem_ptr, StopMem.GetStopMemoryPointer());
  }

  
  /*
   *  ActivateEmailFilter
   *
   *  This function signals that the document DocumentMemory contains an
   *  e-mail header. By default, it is assumed that the document does not
   *  contain an e-mail header.  The main result of calling this function
   *  is that the e-mail header will be ignored, except for the "Subject"
   *  field.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  ActivateEmailFilter()
   */
  public int ActivateEmailFilter()
  {
    return ActivateEmailFilter_helper(lng_document_mem_ptr, StopMem.GetStopMemoryPointer());
  }

  
  /*
   *  SetInputCode
   *
   *  Set the document character code that Extractor uses to process the
   *  input text buffer. The character code is given by CharCodeID.
   *  For more information, please refer to http://extractor.iit.nrc.ca/api.html
   *  or static variables description.
   *
   *  Arguments
   *    1. (int) character code ID
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  SetInputCode(int CharCodeID)
   */
  public int SetInputCode(int CharCodeID)
  {
    return SetInputCode_helper(lng_document_mem_ptr, CharCodeID);
  }

  
  /*
   *  SetOutputCode
   *
   *  Set the document character code that Extractor uses for the output list
   *  of keyphrases. The character code is given by CharCodeID. The character
   *  code is given by CharCodeID.  For more information, please refer to
   *  http://extractor.iit.nrc.ca/api.html or static variables description.
   *
   *  Arguments
   *    1. (int) character code ID
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  SetOutputCode(int CharCodeID)
   */
  public int SetOutputCode(int CharCodeID)
  {
    int_output_code = CharCodeID;
    return SetOutputCode_helper(lng_document_mem_ptr, CharCodeID);
  }

  
  /*
   *  SetDocumentLanguage
   *
   *  Set the language that Extractor uses to process the input text buffer.
   *  The language is given by LanguageID.  For more information, please
   *  refer to http://extractor.iit.nrc.ca/api.html or static variables
   *  description.
   *
   *  Arguments
   *    - (int) Langauge ID
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  SetDocumentLanguage(int LanguageID)
   */
  public int SetDocumentLanguage(int LanguageID)
  {
    return SetDocumentLanguage_helper(lng_document_mem_ptr, LanguageID);
  }

  
  /*
   *  SetNumberPhrases
   *
   *  Set the desired number of output phrases. The default number is seven.
   *  This is the number that will be generated on average; the actual number
   *  of phrases that are output for a given document may be slightly less
   *  or slightly more than the number specified by DesiredNumber.
   *
   *  Arguments
   *    1. (double) desire number of output phrases.
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  SetNumberPhrases(double DesireNumber)
   */
  public int SetNumberPhrases(double DesireNumber)
  {
    return SetNumberPhrases_helper(lng_document_mem_ptr, DesireNumber);
  }

  
  /*
   *  SetHighlightType
   *
   *  Sets the type (i.e., style) of highlight that is generated.  For types
   *  of highlights supported, please refer to Extractor website
   *  http://extractor.iit.nrc.ca/api.html or static variables description.
   *
   *  Arguments
   *    1. (int) Highlight type
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  SetHighlightType(int HighlightType)
   */
  public int SetHighlightType(int HighlightType)
  {
    return SetHighlightType_helper(lng_document_mem_ptr, HighlightType);
  }

  
  /*
   *  ReadDocumentBuffer
   *
   *  This function reads the text in the buffer DocumentBuffer and updates
   *  the memory at DocumentMemory. The processing of the buffer is affected
   *  by StopMemory.  In a typical application, there will be a series of
   *  calls to ExtrReadDocumentBuffer for a given document DocumentMemory.
   *  The idea is that the document is read in chunks. A call to
   *  SignalDocumentEnd signals that the last chunk has been sent
   *  (the end of the given document has been reached).
   *
   *  Notice this function will not properly convert document buffer to
   *  double bytes.  Please use ReadDocumentBuffer(byte[] DocumentBuffer)
   *  instead.
   *
   *  Arguments
   *    1. (String) document buffer
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  ReadDocumentBuffer(String DocumentBuffer)
   */
  public int ReadDocumentBuffer(String DocumentBuffer)
  {
    byte[] char_DocumentBuffer = DocumentBuffer.getBytes();
    return ReadDocumentBuffer(char_DocumentBuffer);
  }

  
  /*
   *  ReadDocumentBuffer
   *
   *  This function reads the text in the buffer DocumentBuffer and updates
   *  the memory at DocumentMemory. The processing of the buffer is affected
   *  by StopMemory.  In a typical application, there will be a series of
   *  calls to ExtrReadDocumentBuffer for a given document DocumentMemory.
   *  The idea is that the document is read in chunks. A call to
   *  SignalDocumentEnd signals that the last chunk has been sent
   *  (the end of the given document has been reached).
   *
   *  Arguments
   *    1. (byte[]) DocumentBuffer
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  ReadDocumentBuffer(byte[] DocumentBuffer)
   */
  public int ReadDocumentBuffer(byte[] DocumentBuffer)
  {
    return ReadDocumentBuffer_helper(lng_document_mem_ptr, StopMem.GetStopMemoryPointer(), DocumentBuffer);
  }

  
  /*
   *  SignalDocumentEnd
   *
   *  Signal that the end of the document has been reached; there will be no
   *  further calls to ExtrReadDocumentBuffer with this particular
   *  DocumentMemory. This signal triggers the generation of the final list
   *  of keyphrases. 
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) return code from Extractor
   *
   *  SignalDocumentEnd()
   */
  public int SignalDocumentEnd()
  {
    return SignalDocumentEnd_helper(lng_document_mem_ptr, StopMem.GetStopMemoryPointer());
  }

  
  /*
   *  GetPhraseListSize
   *
   *  Return an integer value that is the number of keyphrases that were
   *  generated. If there is an error, zero will be returned.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) number of keyphrases
   *
   *  GetPhraseListSize()
   */
  public int GetPhraseListSize()
  {
    int int_return = GetPhraseListSize_helper(lng_document_mem_ptr);
    if (int_last_return_code != 0)
    {
      int_return = 0;
    }
    return int_return;
  }

  
  /*
   *  GetPhraseByIndex
   *
   *  Return the keyphrase in String at index PhraseIndex. PhraseIndex ranges
   *  from zero to PhraseListSize minus one.
   *
   *  Arguments
   *    1. (int) phrase index
   *
   *  Return
   *    - (String) keyphrase at index passed as argument
   *
   *  GetPhraseByIndex(int phraseIndex)
   */
  /*public String GetPhraseByIndex(int PhraseIndex)
  {
    return (new String(GetPhraseByIndex(PhraseIndex)));
  }*/
  
  
  /*
   *  GetPhraseByIndex
   *
   *  Return the keyphrase (in byte array) at index PhraseIndex. PhraseIndex
   *  ranges from zero to PhraseListSize minus one.
   *
   *  Arguments
   *    1. (int) phrase index
   *
   *  Return
   *    - (byte[]) keyphrase at index passed as argument
   *
   *  GetPhraseByIndex(int phraseIndex)
   */
  public byte[] GetPhraseByIndex(int PhraseIndex)
  {
    byte[] bytearr_return = GetPhraseByIndex_helper(lng_document_mem_ptr, PhraseIndex);
    if (int_last_return_code != 0)
    {
      bytearr_return = new byte[0];
    }
    return bytearr_return;
  }


  /*
   *  GetScoreByIndex
   *
   *  Return the score at index phraseIndex.  The number is the score assigned
   *  to index praseIndex. PhraseIndex ranges from zero to PhraseListSize
   *  minus one. The score of a phrase is an estimate of its value as a
   *  keyphrase. Keyphrases are ranked in order of descending score.
   *  This function returns -1 in case of error.
   *
   *  Arguments
   *    1. (int) phraseIndex
   *
   *  Return
   *    - (double) score of keyphrase at index passed as argument
   *
   *  GetScoreByIndex(int phraseIndex)
   */
  public double GetScoreByIndex(int phraseIndex)
  {
    double dbl_return = GetScoreByIndex_helper(lng_document_mem_ptr, phraseIndex);
    if (int_last_return_code != 0)
    {
      dbl_return = -1;
    }
    return dbl_return;
  }

  
  /*
   *  GetDocumentLanguage
   *
   *  Get the language of the document. If the language was set by a call
   *  to SetDocumentLanguage, this function returns the same value that was
   *  specified with ExtrSetDocumentLanguage. If Extractor was allowed to
   *  guess the language, this function returns the best guess.
   *  This function returns -1 in case of error.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) language of the document
   *
   *  GetDocumentLanguage()
   */
  public int GetDocumentLanguage()
  {
    int int_return = GetDocumentLanguage_helper(lng_document_mem_ptr);
    if (int_last_return_code != 0)
    {
      int_return = -1;
    }
    return int_return;
  }

  
  /*
   *  GetHighlightListSize
   *
   *  Return an integer value that is the number of highlights that were
   *  generated. If there is an error, zero will be returned.
   *
   *  Arguments
   *    - none
   *
   *  Return
   *    - (int) number of highlight
   *
   *  GetHighlightListSize()
   */
  public int GetHighlightListSize()
  {
    int int_return = GetHighlightListSize_helper(lng_document_mem_ptr);
    if (int_last_return_code != 0)
    {
      int_return = 0;
    }
    return int_return;
  }

  /*
   *  Comments
   */
  /*public String GetHighlightByIndex(int phraseIndex, String enc)
  {
    return (new String(GetHighlightByIndex(phraseIndex)));
  }*/
  
  /*
   *  GetHighlightByIndex
   *
   *  Return the highlight (in byte array) at index HighlightIndex.
   *  HighlightIndex ranges from zero to HighlightListSize minus one.
   *
   *  Arguments
   *    1. (int) highlight index
   *
   *  Return
   *    - (byte[]) highlight at index passed as argument
   *
   *  GetHighlightByIndex(int HighlightIndex)
   */
  public byte[] GetHighlightByIndex(int HighlightIndex)
  {
    byte[] bytearr_return = GetHighlightByIndex_helper(lng_document_mem_ptr, HighlightIndex);
    if (int_last_return_code != 0)
    {
      bytearr_return = new byte[0];
    }
    return bytearr_return;
  }

  
  /*
   *  GetDocumentProperties
   *
   *  Get various properties of the document.  For properties currently
   *  defined, please refer to http://extractor.iit.nrc.ca/api.html.
   *  This function returns -1 in case of error.
   *
   *  Arguments
   *    1. (int) property ID
   *
   *  Return
   *    - (int) property returned by Extractor
   *
   *  GetDocumentProperties(int PropID)
   */
  public int GetDocumentProperties(int PropID)
  {
    int int_return = GetDocumentProperties_helper(lng_document_mem_ptr, PropID);
    if (int_last_return_code != 0)
    {
      int_return = -1;
    }
    return int_return;
  }
  
  
  /*
   * -------------------------------------------------------------------------
   *
   *  The following are the native methods accessing Extractor dll (WinNT)
   *  or so (Unix).
   *
   * -------------------------------------------------------------------------
   */
  private native int CreateDocumentMemory_helper();

  private native int ClearDocumentMemory_helper(long DocumentMemory);

  private native int ActivateHighlights_helper(long DocumentMemory);

  private native int ActivateHTMLFilter_helper(long DocumentMemory, long StopMemory);

  private native int ActivateEmailFilter_helper(long DocumentMemory, long StopMemory);

  private native int SetInputCode_helper(long DocumentMemory, int CharCodeID);

  private native int SetOutputCode_helper(long DocumentMemory, int CharCodeID);

  private native int SetDocumentLanguage_helper(long DocumentMemory, int LanguageID);

  private native int SetNumberPhrases_helper(long DocumentMemory, double DesireNumber);

  private native int SetHighlightType_helper(long DocumentMemory, int HighlightType);

  private native int ReadDocumentBuffer_helper(long DocumentMemory, long StopMemory, byte[] DocumentBuffer);

  private native int SignalDocumentEnd_helper(long DocumentMemory, long StopMemory);

  private native int GetPhraseListSize_helper(long DocumentMemory);

  private native byte[] GetPhraseByIndex_helper(long DocumentMemory, int phraseIndex);

  private native double GetScoreByIndex_helper(long DocumentMemory, int phraseIndex);

  private native int GetDocumentLanguage_helper(long DocumentMemory);

  private native int GetHighlightListSize_helper(long DocumentMemory);

  private native byte[] GetHighlightByIndex_helper(long DocumentMemory, int HighlightIndex);

  private native String GetErrorMessage_helper(int ErrorCode);

  private native int GetDocumentProperties_helper(long DocumentMemory, int PropID);
}